package hydrap2p.gui;

import hydrap2p.gui.SearchPanel.PopupListener;
import hydrap2p.helper.ServiceConnector;
import hydrap2p.speedlimiter.InvalidParameter;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;

import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.TableColumn;
import javax.swing.table.TableModel;

import org.apache.thrift.TException;

public class SpeedLimiterPanel extends JScrollPane implements TableModelListener
{	
	//the table and model for displaying the modules
	private JTable table;
	
	//the popup menu and its listener
	private ActionListener contextListener = new MenuItemListener();
	private JPopupMenu contextMenu = new TablePopupMenu();
	
	
	//singleton stuff
	private static volatile SpeedLimiterPanel instance;
	
	public static synchronized SpeedLimiterPanel getInstance(){
		if(instance == null){
			synchronized (SpeedLimiterPanel.class){
				if(instance == null){
					instance = new SpeedLimiterPanel();
				}
			}
		}
		return instance;
	}
	//end of singleton stuff
	
	
	/**
	 * Constructor that intializes the table and the panels, the refreshes the module list.
	 * @throws TException 
	 */
	private SpeedLimiterPanel() {
		table = new JTable();
		
		refreshDetails();
	}
	
	//getter for the table
	public JTable getTable(){
		return table;
	}
	
	/**
	 * Makes sure the table is up-to-date
	 */
	public void refreshDetails()
	{
		Map<String, Integer> queues = null;
		try {
			queues = ServiceConnector.getSpeedLimiter().getQueues();
		} catch (TException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		//set up the table contents
		Vector<String> columnNames = new Vector<String>();
			columnNames.add("Queue");
			columnNames.add("Limit");
		Vector<Vector<String>> data = new Vector<Vector<String>>();
		
		//add the results, if there are any
		if (queues != null)
		{
			Set<String> keys = queues.keySet();
			
			for (String queueName : keys)
			{
				Vector<String> v = new Vector<String>();
				v.add(queueName);
				v.add(String.valueOf(queues.get(queueName)));
				data.add(v);
			}
		}
		
		table = new JTable(data, columnNames) { public boolean isCellEditable(int rowIndex, int vColIndex) { if (vColIndex == 0) return false; else return true;}};
		table.addMouseListener(new PopupListener());
        table.getModel().addTableModelListener(this);

		setViewportView(table);
	}

	//update the modules when the table's data changes
    public void tableChanged(TableModelEvent e) {
        TableModel model = table.getModel();
    	
    	int row = e.getFirstRow();
        int column = e.getColumn();
        
        if (row < 0) return;
        if (column != 1) return;
        
        String data = (String)model.getValueAt(row, column);
        String name = (String)model.getValueAt(row, 0);
        
        String logMessage = "Limit changed to " + data + ".";
        
        int checkedData = Integer.parseInt(data);
        int originalValue = 0;
        
        //correct invalid values
        Map<String, Integer> queues = null;
		try {
			queues = ServiceConnector.getSpeedLimiter().getQueues();
		} catch (TException e0) {
			// TODO Auto-generated catch block
			e0.printStackTrace();
		}
		
		if (queues != null)	//and it really SHOULDN'T
			originalValue = queues.get(name);
		
		//check for validity and reset if necessary
		if (checkedData < 0) //or it's too large, I guess; add as necessary
		{
			checkedData = originalValue;
			JOptionPane.showMessageDialog(null, "The value you entered is invalid.", "Invalid Entry", JOptionPane.ERROR_MESSAGE);
			logMessage = "User attempted to change limit to an invalid value; change rejected.";
		}
		
        
        try {
        	ServiceConnector.getSpeedLimiter().setQueueLimit(name, checkedData);
        	GUIDataHandler.getInstance().log(GUIDataHandler.LOG_VERBOSE, name, logMessage);
		} catch (TException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (InvalidParameter e2) {
			// TODO Auto-generated catch block
			e2.printStackTrace();
		}
		
		refreshDetails();
    }
    
    class MenuItemListener implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent e) {
			/*if (e.getActionCommand() == "properties")
			{
				CommandInvoker.getInstance().invokeCommand(new Cmd_StartupManagerPanel_ShowModuleProperties());
			}*/
		}
	}
    
	private class TablePopupMenu extends JPopupMenu {
        public TablePopupMenu() {
            super();
            /*
            addNewStringItem("Properties", "properties");
            */
            
        }
        @Override
        public void show(Component c, int x, int y) {
            int[] l = table.getSelectedRows();
            super.show(c, x, y);
        }
        
        private void addNewStringItem(String name, String command)
        {
        	JMenuItem temp = new JMenuItem(name);
        	temp.addActionListener(contextListener);
        	temp.setActionCommand(command);
        	add(temp);
        }
    }
	
	class PopupListener extends MouseAdapter {
	    public void mousePressed(MouseEvent e) {
	        maybeShowPopup(e);
	    }

	    public void mouseReleased(MouseEvent e) {
	        maybeShowPopup(e);
	    }

	    private void maybeShowPopup(MouseEvent e) {
	        if (e.isPopupTrigger()) {
	        	contextMenu.show(e.getComponent(), e.getX(), e.getY());
	        }
	    }
	}
}
